import loginApi from '@/api/user/loginApi'
import loginByWxCodeApi from '@/api/user/loginByWxCodeApi'
import userCenterBaseInfoApi from '@/api/userCenter/userCenterBaseInfoApi'
import { getAppNav } from '@/App'
import LocalStorageKey from '@/constant/LocalStorageKey'
import { tabBarKeyList } from '@/layout/CTabBar/CTabBar'
import ILoginForm from '@/model/form/user/ILoginForm'
import IUserBaseInfoVO from '@/model/vo/user/IUserBaseInfoVO'
import { useAppDispatch, useAppSelector } from '@/store'
import { setUserBaseInfo } from '@/store/user/userSlice'
import appApi from '@/support'
import { ToastError, ToastInfo, ToastSuccess } from '@/util/CommonUtil'
import { maxTryNum, timeoutMsg } from '@/util/http/interceptor'
import { getQueryVariable } from '@/util/UrlUtil'
import { passwordRSAEncrypt } from '@/util/UserUtil'
import { Button, Checkbox, Form, Input, Space } from 'antd-mobile'
import { Dispatch, SetStateAction, useEffect, useState } from 'react'
import LoginRegisterBase from '../components/LoginRegisterBase/LoginRegisterBase'

// 登录成功之后的操作
function loginSuccessHandler(
  jwt: string,
  doSetUserBaseInfo: (userBaseInfo: IUserBaseInfoVO) => void
) {
  localStorage.setItem(LocalStorageKey.JWT, jwt) // 存储 jwt
  // 获取用户基本信息
  userCenterBaseInfoApi().then(({ data }) => {
    ToastInfo('欢迎回来 (oﾟ▽ﾟ)o', 3, null, true)
    doSetUserBaseInfo(data.data)
    getAppNav()(tabBarKeyList[tabBarKeyList.length - 1]) // 跳转：最后一个 path
  })
}

export default function Login() {
  const [element, setElement] = useState<JSX.Element | null>(null)
  const appDispatch = useAppDispatch()

  // 更新 userBaseInfo
  function doSetUserBaseInfo(userBaseInfo: IUserBaseInfoVO) {
    appDispatch(setUserBaseInfo(userBaseInfo))
  }

  useEffect(() => {
    if (appApi.type === -1) {
      setElement(<LoginElement />)
      return
    }

    const code = getQueryVariable('code')
    if (!code) {
      if (appApi.type === 1) {
        appApi.sendMsg({ code: 1 })
      }
      return
    }
    ToastInfo('登录中...', 0, 'loading')
    loginByWxCodeApi({ code })
      .then(({ data }) => {
        loginSuccessHandler(data.data, doSetUserBaseInfo)
      })
      .catch(() => {
        getAppNav()(tabBarKeyList[tabBarKeyList.length - 1]) // 跳转：最后一个 path
      })
  }, [])

  return element
}

// Login组件的页面元素
function LoginElement() {
  const [loading, setLoading] = useState(false)
  const [rememberMe, setRememberMe] = useState(false)
  const [hiddenFlag, setHiddenFlag] = useState(false)

  const rsaPublicKey = useAppSelector((state) => state.common.rsaPublicKey)
  const appDispatch = useAppDispatch()

  // 更新 userBaseInfo
  function doSetUserBaseInfo(userBaseInfo: IUserBaseInfoVO) {
    appDispatch(setUserBaseInfo(userBaseInfo))
  }

  return (
    <LoginRegisterBase name="用户登录">
      <Form
        onFinish={(form: ILoginForm) => {
          if (loading) return
          form.rememberMe = rememberMe
          form.hiddenFlag = hiddenFlag
          submitClick(form, setLoading, rsaPublicKey, doSetUserBaseInfo)
        }}
        footer={
          <Space direction="vertical" block>
            <Button
              block
              type="submit"
              color="primary"
              size="large"
              loading={loading}
            >
              登录
            </Button>
            <Button
              color="warning"
              block
              disabled={loading}
              size="middle"
              onClick={() => getAppNav()('/register')}
            >
              去注册
            </Button>
            <Button
              block
              disabled={loading}
              size="middle"
              onClick={() =>
                getAppNav()(tabBarKeyList[tabBarKeyList.length - 1])
              }
            >
              返回
            </Button>
            <div className="flex jc-e f-16 m-t-10">
              <a
                onClick={() => {
                  if (loading) return
                  getAppNav()('/forgotPasswordSend')
                }}
              >
                忘记密码
              </a>
            </div>
          </Space>
        }
      >
        <Form.Item
          disabled={loading}
          name="account"
          rules={[{ required: true, message: '请输入手机号/邮箱' }]}
        >
          <Input placeholder="手机号/邮箱" clearable />
        </Form.Item>
        <Form.Item
          disabled={loading}
          name="password"
          rules={[{ required: true, message: '请输入密码' }]}
        >
          <Input placeholder="密码" clearable type="password" />
        </Form.Item>
        <Form.Item>
          <div className="w100 flex jc-sb">
            <Checkbox
              disabled={loading}
              checked={rememberMe}
              onChange={(checked) => {
                setRememberMe(checked)
              }}
            >
              记住我
            </Checkbox>
            <Checkbox
              disabled={loading}
              checked={hiddenFlag}
              onChange={(checked) => {
                setHiddenFlag(checked)
              }}
            >
              隐身登录
            </Checkbox>
          </div>
        </Form.Item>
      </Form>
    </LoginRegisterBase>
  )
}

// 点击提交按钮
function submitClick(
  form: ILoginForm,
  setLoading: Dispatch<SetStateAction<boolean>>,
  rsaPublicKey: string,
  doSetUserBaseInfo: (userBaseInfo: IUserBaseInfoVO) => void
) {
  setLoading(true) // 设置 loading状态
  const passwordTemp = form.password // 密码原始值

  form.password = passwordRSAEncrypt(passwordTemp, rsaPublicKey)

  if (form.hiddenFlag) {
    // socket 连接状态：1 在线 2 隐身
    localStorage.setItem(LocalStorageKey.SOCKET_TYPE, '2')
  } else {
    localStorage.setItem(LocalStorageKey.SOCKET_TYPE, '1')
  }

  doLoginApi(
    form,
    maxTryNum,
    setLoading,
    passwordTemp,
    rsaPublicKey,
    doSetUserBaseInfo
  )
}

// 调用登录接口
function doLoginApi(
  form: ILoginForm,
  maxTryNum: number,
  setLoading: Dispatch<SetStateAction<boolean>>,
  passwordTemp: string,
  rsaPublicKey: string,
  doSetUserBaseInfo: (userBaseInfo: IUserBaseInfoVO) => void
) {
  if (maxTryNum < 0) {
    ToastError(timeoutMsg, 5)
    setLoading(false) // 取消 loading状态
    return
  }
  loginApi(form)
    .then(({ data }) => {
      loginSuccessHandler(data.data, doSetUserBaseInfo)
    })
    .catch((e) => {
      if (e.message.includes('timeout')) {
        form.password = passwordRSAEncrypt(passwordTemp, rsaPublicKey)
        doLoginApi(
          form,
          maxTryNum - 1,
          setLoading,
          passwordTemp,
          rsaPublicKey,
          doSetUserBaseInfo
        )
      } else {
        ToastError(e.message, 5)
        setLoading(false) // 取消 loading状态
      }
    })
}
